package com.apobates.jforum2.troll.forum.controller;

import com.apobates.jforum2.troll.attention.core.decorater.ForumEntityIcoDecorder;
import com.apobates.jforum2.troll.forum.biz.BoardGroupService;
import com.apobates.jforum2.troll.forum.biz.BoardService;
import com.apobates.jforum2.troll.forum.entity.Board;
import com.apobates.jforum2.troll.forum.entity.BoardGroup;
import com.apobates.jforum2.troll.forum.entity.BoardGroupGraph;
import com.apobates.jforum2.troll.forum.mapper.BoardGroupVoMapperEntity;
import com.apobates.jforum2.troll.forum.mapper.BoardVoMapperEntity;
import com.apobates.jforum2.troll.forum.stub.vo.BoardGroupCollectVo;
import com.apobates.jforum2.troll.forum.stub.vo.BoardGroupVo;
import com.apobates.jforum2.troll.forum.stub.vo.BoardVo;
import com.apobates.jforum2.troll.regular.ImageIOMeta;
import com.apobates.jforum2.troll.utils.core.ResponseResult;
import java.net.URL;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 版块组Api
 *
 * @author xiaofanku
 * @since 20201113
 */
@RestController
@RequestMapping("/boardgroup")
public class BoardGroupController {
    @Autowired
    private BoardGroupService boardGroupService;
    @Autowired
    private BoardService boardService;
    @Value("${img.bucket.domain}")
    private String imageBucketDomain;
    @Value("${img.bucket.upload.direct}")
    private String imageBucketUploadDirect;

    //1:指定的版块组
    @GetMapping("/{volume}")
    public ResponseEntity<BoardGroupVo> getVolumeById(@PathVariable("volume")int boardGroupId){
        Supplier<Optional<BoardGroup>> rs = ()->(boardGroupId>0)?boardGroupService.get(boardGroupId):Optional.empty();
        ResponseResult<BoardGroupVo> rr = ResponseResult.ofEntityVo(rs, new BoardGroupVoMapperEntity());
        return ResponseEntity.status(rr.getCode()).contentType(MediaType.APPLICATION_JSON).body(rr.getEntity());
    }
    
    //2:指定版块组的图标
    @GetMapping("/{volume}/ico/{scale}")
    public ResponseEntity<String> getBoardIco(@PathVariable("volume")int boardGroupId, @PathVariable("scale")String scale){
        Optional<BoardGroup> volume = (boardGroupId>0)?boardGroupService.get(boardGroupId):Optional.empty();
        if(!volume.isPresent()){
            return ResponseEntity.status(400).body("版块不存在");
        }
        String boardIcoURL = null;
        String defaultIco = String.format("%s/%s/ico/default_icon.png", getImageIOMeta().getImageBucketDomain(), getImageIOMeta().getUploadImageDirectName());
        try {
            boardIcoURL = new ForumEntityIcoDecorder(getImageIOMeta().getImageBucketDomain(), getImageIOMeta().getUploadImageDirectName())
                    .decode(volume.get().getImageAddr(), scale)
                    .map(URL::toString)
                    .orElse(defaultIco);
        }catch (java.net.MalformedURLException e){
            boardIcoURL = defaultIco;
        }
        //
        ResponseResult<String> rr = ResponseResult.Helper.ofOptional(Optional.ofNullable(boardIcoURL));
        return ResponseEntity.status(rr.getCode()).contentType(MediaType.APPLICATION_JSON).body(rr.getEntity());
    }
    //3:所有的版块组
    @GetMapping("/all")
    public List<BoardGroupVo> getAllUsedVolumes(){
        List<BoardGroup> rs = boardGroupService.getAllUsed();
        return rs.stream().map(BoardGroupVoMapperEntity.mapper()).collect(Collectors.toList());
    }
    //4:所有的版块组,级联加载版块组下的版块
    @GetMapping("/all/cascade/{defed}")
    public List<BoardGroupCollectVo> getAllCascadeUsedBoard(@PathVariable("defed")int containsDefault){
        boolean cdval = containsDefault == 1;
        return boardGroupService.getAllUsedAndBoard(cdval).stream().map(tmp->{
            BoardGroupCollectVo a =  boardGroupCollectVoMapper().apply(tmp);
            a.setBoardes(tmp.getBoardes().stream().map(BoardVoMapperEntity.mapper()).collect(Collectors.toCollection(() -> new TreeSet<BoardVo>(Comparator.comparingLong(BoardVo::getRanking)))));
            return a;
        }).collect(Collectors.toList());
    }
    public static Function<BoardGroupGraph, BoardGroupCollectVo> boardGroupCollectVoMapper(){
        return bgg -> {
            BoardGroupCollectVo bgcv = new BoardGroupCollectVo();
            //
            bgcv.setBoardGroupVo(BoardGroupVoMapperEntity.mapper().apply(bgg.getBoardGroup()));
            return bgcv;
        };
    }
    //5:指定的版块组,级联加载版块组下的版块
    @GetMapping("/{volume}/cascade")
    public ResponseEntity<BoardGroupCollectVo> getCascadeUsedBoard(@PathVariable("volume")int boardGroupId){
        CompletableFuture<Optional<BoardGroup>> groupData = CompletableFuture.supplyAsync(()->boardGroupService.get(boardGroupId)).completeOnTimeout(Optional.empty(), 1, TimeUnit.SECONDS);
        CompletableFuture<Stream<Board>> groupBoardData = CompletableFuture.supplyAsync(()->boardService.getAllByVolumesId(boardGroupId)).completeOnTimeout(Stream.empty(), 1, TimeUnit.SECONDS);
        Optional<BoardGroupCollectVo> data = groupData.thenCombine(groupBoardData, (boardGroupOptional, boardStream)->{
            return boardGroupOptional.map(bg->{
                BoardGroupCollectVo tmp = new BoardGroupCollectVo();
                tmp.setBoardGroupVo(BoardGroupVoMapperEntity.mapper().apply(bg));
                tmp.setBoardes(boardStream.map(BoardVoMapperEntity.mapper()).collect(Collectors.toCollection(() -> new TreeSet<BoardVo>(Comparator.comparingLong(BoardVo::getRanking)))));
                return tmp;
            });
        }).orTimeout(1, TimeUnit.SECONDS).join();
        //
        ResponseResult<BoardGroupCollectVo> rr = ResponseResult.Helper.ofOptional(data);
        return ResponseEntity.status(rr.getCode()).contentType(MediaType.APPLICATION_JSON).body(rr.getEntity());
    }
    
    private ImageIOMeta getImageIOMeta(){
        return new ImageIOMeta(){
            @Override
            public String getImageBucketDomain() {
                return imageBucketDomain;
            }

            @Override
            public String getUploadImageDirectName() {
                return imageBucketUploadDirect;
            }
        };
    }
}
/*
/boardgroup/{volume}
/boardgroup/{volume}/ico/{scale}
/boardgroup/all
/boardgroup/all/cascade/{defed}
/boardgroup//{volume}/cascade
* */